﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Chinesys.Entities.Constants;
using Chinesys.Entities;
using Chinesys.UI.Helpers;
using Chinesys.Domain;
using Chinesys.Domain.BizRules;
using Chinesys.Domain.InputValidations;

namespace Chinesys.UI.Orders
{
    public partial class CustomerOrders : PageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            CheckUserInRole(Constants.Roles.Customer);

            Master.PageTitle = "Mi Carrito de compras";

            if (!IsPostBack)
            {
                LoadLists();
            }
        }

        private void LoadLists()
        {
            OrderEntity order = FetchOrderForCustomer(SecurityHelper.GetLoggedCustomer(User.Id).Id);

            if (order != null)
            {
                rptProductsGrid.DataSource = order.OrderDetails.ConvertAll<DetailView>(d => new DetailView(d));
                rptProductsGrid.DataBind();
            }
        }

        private OrderEntity FetchOrderForCustomer(int customerID)
        {
            OrderEntity order = OrderDomain.GetActiveOrderForCustomer(customerID);
            if (order == null || order.OrderDetails == null)
                hdnBizRulesException.Value = "Usted no ha realizado ningun pedido. Agregue productos al carrito y luego regrese.";

            return order;
        }

        private bool HasProducts(OrderEntity order)
        {
            if (order == null || order.OrderDetails == null || !order.OrderDetails.Any())
                return false;

            return true;
        }

        protected void rptProductsGrid_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            if (e.CommandName == "RemoveFromCart")
            {
                //Traigo el pedido para el cliente.
                OrderEntity order = FetchOrderForCustomer(SecurityHelper.GetLoggedCustomer(User.Id).Id);

                //Consigo los parametros necesarios desde la pagina.
                int detailID = Convert.ToInt32(e.CommandArgument);

                //Quito el producto del carrito.
                OrderDetailEntity detail = RemoveDetailForOrder(order, detailID);

                //Guardo los cambios en el pedido 
                //validando todos los campos de entrada y realizando
                //las validaciones de negocio necesarias.
                try
                {
                    OrderDomain.Save(order);

                    lblInfo.Text = string.Format("Se ha quitado del pedido numero '{0}': la cantidad de {1} {2} con un valor de {3} pesos argentinos cada unidad. Se ha reestablecido el saldo de su cuenta.",
                                                    order.Id,
                                                    detail.Quantity,
                                                    detail.Product.Name,
                                                    (detail.Product.Price * order.DolarPrice).ToString("C"));
                    lblInfo.Visible = true;

                    LoadLists();
                }
                catch (InputValidationException ex)
                {
                    validationSummary.Errors = ex.Validator.Errors;
                }
                catch (BizRulesException ex)
                {
                    hdnBizRulesException.Value = ex.Message;
                }
            }
        }

        private OrderDetailEntity RemoveDetailForOrder(OrderEntity order, int detailID)
        {
            if (order != null && order.OrderDetails != null)
            {
                OrderDetailEntity detail = order.OrderDetails.SingleOrDefault(det => det.Id == detailID);

                if (detail == null)
                    throw new BizRulesException("El producto seleccionado no se encuentra en el carrito. Contacte con el administrador para mas información.");

                if (detail.CurrentState != RowState.Original)
                    throw new BizRulesException("El estado del producto seleccionado es inconsistente. Contacte con el administrador para mas información.");

                detail.CurrentState = RowState.Deleted;

                return detail;
            }
            else
                throw new BizRulesException("No se pudo quitar el producto del carrito. Contacte con el administrador para mas información.");
        }

        class DetailView
        {
            public DetailView(OrderDetailEntity detail)
            {
                this.detail = detail;
            }

            private OrderDetailEntity detail;

            public int ID
            {
                get { return detail.Id; }
                set { detail.Id = value; }
            }

            public int OrderID
            {
                get { return detail.OrderId; }
                set { detail.OrderId = value; }
            }

            public int ProductID
            {
                get { return detail.ProductId; }
                set { detail.ProductId = value; }
            }

            public decimal UnitPrice
            {
                get { return detail.UnitPrice; }
                set { detail.UnitPrice = value; }
            }

            public int Quantity
            {
                get { return detail.Quantity; }
                set { detail.Quantity = value; }
            }

            public decimal SubtotalInDolars
            {
                get
                {
                    return Quantity * ProductPriceInDolars;
                }
            }

            public string ProductName
            {
                get { return detail.Product.Name; }
                set { detail.Product.Name = value; }
            }

            public string ProductDescription
            {
                get { return detail.Product.Description; }
                set { detail.Product.Description = value; }
            }

            public decimal ProductPriceInDolars
            {
                get { return detail.Product.Price; }
                set { detail.Product.Price = value; }
            }

            public string ProductImageURL
            {
                get { return detail.Product.ImageSrc; }
                set { detail.Product.ImageSrc = value; }
            }
        }
    }
}